﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using orz.mouxianyu.Models;

namespace orz.mouxianyu.Services.lmpl
{
    public class LoginService : ILoginService
    {
        public IConfiguration Configuration { get; }

        public LoginService(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public reLoginDTO Login(LoginDTO body)
        {
            try
            {
                if (body.userName == "咸鱼框架" && body.passWord == "orz.mouxianyu")
                {
                    reLoginDTO re = new reLoginDTO();
                    re.UID = "00001";
                    re.userName = "某咸鱼orz";
                    re.role = "admins";
                    re.remsg = "登录成功";
                    re.token = getToken(re.UID, re.userName, re.role);
                    return re;
                }
                else
                {
                    throw new Exception("用户名或密码错误");
                }
                /*
                 注：以上仅为为测试token的登录示例代码，实际生产建议编写存储过程验证数据库用户表
                    例：
                    var result = _connection.Query<reLoginDTO>("Login", new { body.userName, body.passWord }, transaction: _stran, commandType: CommandType.StoredProcedure).SingleOrDefault();
                    用户密码建议以密文方式存储在数据库里，本框架提供加密工具类HashPass（orz.mouxianyu.Extensions.ToolClass.HashPass）,支持十几种主流加密方式
                    以下为示例存储过程，实际开发请按照自己的需求编写登录逻辑
                    ALTER PROCEDURE [dbo].[Login]
                    	-- Add the parameters for the stored procedure here
                    	
                    	@UID varchar(50),@PassWord varchar(50)
                    AS
                    BEGIN
                    	-- SET NOCOUNT ON added to prevent extra result sets from
                    	-- interfering with SELECT statements.
                    	SET NOCOUNT ON;
                    
                        -- Insert statements for procedure here
                    	if not exists(select * from [dbo].[用户数据表] where userName = @userName AND passWord = @passWord)
                    	begin
                    		raiserror('用户名或密码错误',16,1)
                    	end
                    	begin
                    		select UID,userName,role,'登录成功' as remsg from [dbo].[用户数据表] where userName = @userName
                    		RETURN
                    	end
                    
                    END
                 */
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {

            }
        }

        /// <summary>
        /// 生成token
        /// </summary>
        /// <param name="UID">用户id</param>
        /// <param name="userName">用户名</param>
        /// <param name="role">用户身份（user/admin）</param>
        /// <returns></returns>
        private tokenDTO getToken(string UID, string userName, string role)
        {
            var claims = new List<Claim>();
            var claim = new Claim("jti", Guid.NewGuid().ToString());
            claims.Add(claim);
            claim = new Claim("iat", DateTime.Now.ToString());
            claims.Add(claim);
            claim = new Claim("rol", role);
            claims.Add(claim);
            claim = new Claim("id", UID);
            claims.Add(claim);
            /*
                iss: The issuer of the token，token 是给谁的
                sub: The subject of the token，token 主题
                exp: Expiration Time。 token 过期时间，Unix 时间戳格式
                iat: Issued At。 token 创建时间， Unix 时间戳格式
                jti: JWT ID。针对当前 token 的唯一标识
             */
             string a = Configuration["JWT:SecurityKey"];
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:SecurityKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            var authTime = DateTime.UtcNow;
            var expiresAt = authTime.AddDays(7);//七天过期,这里可设置任意过期时长

            var token = new JwtSecurityToken(
                issuer: "orz.mouxianyu",
                audience: "orz.mouxianyu",
                claims: claims,
                expires: expiresAt,
                signingCredentials: creds);

            tokenDTO re = new tokenDTO();
            re.access_token = new JwtSecurityTokenHandler().WriteToken(token);
            re.token_type = "Bearer";
            return re;
        }
    }
}
